%{
	#include <stdlib.h>
	#include <stdio.h>
	#include <vector>

	extern int yyerror ( char* );
	extern int yylex ();

	#include "attributs.hpp"

	#include "TableIdent.hpp"
	extern TableIdent ti;

	#include "TableSymb.hpp"
	TableSymb ts;

	#include "actions.hpp"
%}

%union {
	tAttrExpr e;
	tAttrVarExpr ve;
	tAttrEntier i;
	tAttrReel d;
	tAttrListIdent li;
	tAttrIdent ident;
	tAttrBaseType bt;
}

%token KW_PROGRAM
%token KW_CONST
%token KW_TYPE
%token KW_VAR
%token KW_ARRAY
%token KW_OF
%token KW_RECORD
%token KW_BEGIN
%token KW_END
%token KW_DIV
%token KW_MOD
%token KW_AND
%token KW_OR
%token KW_XOR
%token KW_NOT
%token KW_IF
%token KW_THEN
%token KW_ELSE
%token KW_WHILE
%token KW_DO
%token KW_REPEAT
%token KW_UNTIL
%token KW_FOR
%token KW_TO
%token KW_DOWNTO
%token KW_PROC
%token KW_FUNC
%token KW_NIL
%token KW_INTEGER
%token KW_REAL
%token KW_BOOLEAN
%token KW_CHAR
%token KW_STRING

%token SEP_DOTS;
%token SEP_SCOL;
%token SEP_COMMA;
%token SEP_DOT;
%token SEP_DOTDOT;
%token SEP_CO;
%token SEP_CF;
%token SEP_PO;
%token SEP_PF;

%token OP_ADD
%token OP_SUB
%token OP_MUL
%token OP_DIV
%token OP_AFFECT
%token OP_EXP
%token OP_PTR

%token <ident>  TOK_IDENT
%token <i>  	TOK_INTEGER
%token <d>  	TOK_REAL
%token TOK_BOOLEAN
%token TOK_STRING

%type <e>  	expr
%type <e>  	mathExpr
%type <e>  	atomExpr
%type <ve>  varExpr
%type <e>  	listInstr
%type <e>  	instr
%type <li>	listIdent
%type <bt>	baseType

%start program

%nonassoc OP_AFFECT OP_NEQ OP_GT OP_LT OP_GTE OP_LTE
%left OP_ADD OP_SUB KW_OR KW_XOR
%left OP_MUL OP_SLASH KW_AND KW_DIV KW_MOD
%right KW_NOT OP_NEG OP_POS
%left OP_EXP
%nonassoc OP_PTR
%nonassoc OP_DOT
%left SEP_CO

%nonassoc KW_IFX
%nonassoc KW_ELSE

%%

program			: 	programHeader SEP_SCOL block SEP_DOT
				;

programHeader	: 	KW_PROGRAM TOK_IDENT
		  				{ actionProgHeader($2); }
				;

block			: 	blockDeclConst blockDeclType blockDeclVar
				  		blockDeclFunc blockCode
				;

blockDeclConst  :   KW_CONST listDeclConst
                |
                ;

listDeclConst   :   listDeclConst declConst
                |   declConst
                ;

declConst       :   TOK_IDENT OP_AFFECT	expr SEP_SCOL
						{ actionDeclConst($1, $3); }
                ;


blockDeclType   :   KW_TYPE listDeclType
				|
				;

listDeclType    :   listDeclType declType
                |   declType
                ;

declType        :   TOK_IDENT OP_AFFECT type SEP_SCOL


blockDeclVar    :   KW_VAR listDeclVar
				|
                ;

listDeclVar     :   listDeclVar declVar
				|   declVar
                ;

declVar         :   listIdent SEP_DOTS baseType SEP_SCOL
						{ actionDeclVar($1, $3); }
				;

listIdent       :   listIdent SEP_COMMA TOK_IDENT
						{ actionListIdent($$, $3); }
				|   TOK_IDENT
						{ actionListIdentDernier($$, $1); }
				;

blockDeclFunc   :   listDeclFunc SEP_SCOL
                |
                ;

listDeclFunc	:
			 	;

type            :   /*UserType*/
                |   baseType
                ;

/*
UserType        :   EnumType
                |   InterType
                |   ArrayType
                |   RecordType
                |   PointerType
*/

baseType		:	TOK_IDENT
		  		|	KW_INTEGER
					{ actionBaseTypeInt($$); }
				|	KW_REAL
					{ actionBaseTypeReal($$); }
                |   KW_BOOLEAN
                |   KW_CHAR
                |   KW_STRING
                ;

blockCode       :   KW_BEGIN listInstr KW_END
                |   KW_BEGIN listInstr SEP_SCOL KW_END
                |   KW_BEGIN KW_END

/* -------------- */

listInstr:			listInstr SEP_SCOL instr
		 		|	instr
				;
/*
						{ actionListInstr($$); }
				| 	instr SEP_COL listInstr
*/

instr			:	varExpr OP_AFFECT expr
						{ actionInstr($$, $1, $3); }
				;

expr			:	atomExpr
				| 	varExpr
				| 	mathExpr
				;

atomExpr		:	TOK_INTEGER
						{ actionConstante($$, $1); }
				| 	TOK_REAL
						{ actionConstante($$, $1); }
				;

varExpr			:
				  	TOK_IDENT
						{ actionIdent($$, $1); }
				| 	TOK_IDENT OP_PTR
						{ actionPtr($$, $1); }
				;

mathExpr		:
	  			  	expr OP_ADD expr
						{ actionAdd($$, $1, $3); }
				| 	expr OP_SUB expr
						{ actionSub($$, $1, $3); }
				| 	expr OP_MUL expr
						{ actionMul($$, $1, $3); }
				| 	expr OP_DIV expr
						{ actionDiv($$, $1, $3); }
				| 	expr OP_EXP expr
						{ actionExp($$, $1, $3); }
				| 	OP_SUB expr %prec OP_NEG
						{ actionSub($$, $2); }
				| 	OP_ADD expr %prec OP_POS
						{ actionSub($$, $2); }
				| 	SEP_PO expr SEP_PF
						{ actionBrackets($$, $2); }
				;

/* End of grammar.  */
%%
